# -*- coding: utf-8 -*-
# Standard Library
import asyncio
import os

# Third Party Libraries
import aiohttp
import pytest_asyncio
import uvloop
import yarl

import git_cdn.util
from git_cdn import app as git_cdn_app

# pylint: disable=unused-argument,redefined-outer-name,consider-using-f-string,protected-access

GITLAB_REPO_TEST_GROUP = os.getenv("GITLAB_REPO_TEST_GROUP", "grouperenault/repo_test")
GITSERVER_UPSTREAM = os.getenv("GITSERVER_UPSTREAM", "https://gitlab.com/")
MANIFEST_PATH = f"{GITLAB_REPO_TEST_GROUP}/test_git_cdn.git"
CREDS = os.getenv("CREDS", "gitlab-ci-token:{}".format(os.getenv("CI_JOB_TOKEN")))
# For consistency, pytest should not share prometheus metrics across processes
if "PROMETHEUS_MULTIPROC_DIR" in os.environ:
    del os.environ["PROMETHEUS_MULTIPROC_DIR"]


@pytest_asyncio.fixture
def tmpworkdir(tmpdir):
    git_cdn.util.WORKDIR = tmpdir / "gitCDN"
    yield tmpdir


@pytest_asyncio.fixture
def app(tmpworkdir):
    yield git_cdn_app.make_app(GITSERVER_UPSTREAM)


@pytest_asyncio.fixture
def app_with_metrics(monkeypatch, tmpworkdir):
    monkeypatch.setenv("PROMETHEUS_ENABLED", "true")
    yield git_cdn_app.make_app(GITSERVER_UPSTREAM)


@pytest_asyncio.fixture(scope="module", params=[asyncio, uvloop])
def cdn_event_loop(request):
    loop = None
    if request.param is asyncio:
        loop = asyncio.new_event_loop()
        # FastChildWatcher is failing our tests with following exception
        # RuntimeError: asyncio.get_child_watcher() is not activated,
        #   subprocess support is not installed.
        # Maybe because FastChildWatcher requires a running event loop in the main thread to work
        asyncio.set_child_watcher(asyncio.ThreadedChildWatcher())

    elif request.param is uvloop:
        loop = uvloop.new_event_loop()

    asyncio.set_event_loop(loop)

    yield loop

    if not loop.is_closed():
        loop.close()


@pytest_asyncio.fixture
def header_for_git(request):
    return ["-c", f"http.extraheader=X-CI-INTEG-TEST: {request.node.nodeid}"]


@pytest_asyncio.fixture
async def client_with_localapp_with_metrics(
    aiohttp_client, monkeypatch, app_with_metrics, creds=CREDS, **kwargs
):
    if "UNDER_TEST_APP" not in os.environ:
        app = app_with_metrics()
        c = await aiohttp_client(app, **kwargs)
        c.baseurl = f"http://{creds}@localhost:{c._server.port}"
        return c


@pytest_asyncio.fixture
async def client_with_localapp(aiohttp_client, app, creds=CREDS, **kwargs):
    if "UNDER_TEST_APP" not in os.environ:
        app = app()
        c = await aiohttp_client(app, **kwargs)
        c.baseurl = f"http://{creds}@localhost:{c._server.port}"
        return c


@pytest_asyncio.fixture
async def simple_client():
    if "UNDER_TEST_APP" in os.environ:
        session = None
        url = yarl.URL(os.getenv("UNDER_TEST_APP"))
        user, password = CREDS.split(":")
        url = url.with_user(user).with_password(password)
        print(f"URL: {url}")
        session = aiohttp.ClientSession(os.getenv("UNDER_TEST_APP"))
        session.baseurl = url
        yield session

        if session:
            session.close()
    else:
        yield None


@pytest_asyncio.fixture
async def client_with_metrics(simple_client, client_with_localapp_with_metrics):
    if "UNDER_TEST_APP" in os.environ:
        client = simple_client
    else:
        client = client_with_localapp_with_metrics
    return client


@pytest_asyncio.fixture
async def client(simple_client, client_with_localapp):
    if "UNDER_TEST_APP" in os.environ:
        client = simple_client
    else:
        client = client_with_localapp
    return client
